package features

import (
	"fmt"
	"os"
	"strings"
	"text/template"
)

func GenerateFile(info map[string]interface{}, dbs *DBS) {

	structPath := "./code/" + dbs.PackageName
	servicePath := "./code/" + dbs.ServicePackageName

	//创建目录
	os.MkdirAll(structPath, os.ModePerm)
	os.MkdirAll(servicePath, os.ModePerm)

	//拼接文件名称
	structFileName := structPath + "/" + info["structName"].(string) + ".go"
	serviceFileName := servicePath + "/" + info["structName"].(string) + "Service.go"

	structFile, _ := os.Create(structFileName)
	serviceFile, _ := os.Create(serviceFileName)

	//关闭流
	defer func() {
		structFile.Close()
		serviceFile.Close()
	}()

	structTemplate, err1 := template.ParseFiles("./templates/struct.txt")
	if err1 != nil {
		fmt.Println(err1)
	}
	//写入结构体
	structTemplate.Execute(structFile, info)

	serviceTemplate, err2 := template.ParseFiles("./templates/service.txt")
	if err2 != nil {
		fmt.Println(err2)
	}
	//写入逻辑代码
	serviceTemplate.Execute(serviceFile, info)
}

//首字母大写
func firstToUpper(str string) string {
	str = strings.ToUpper(string(str[0:1])) + string(str[1:])
	return str
}

//首字母小写
func firstToLower(str string) string {
	str = strings.ToLower(string(str[0:1])) + string(str[1:])
	return str
}

//驼峰
func camelCaseName(name string) string {
	names := strings.Split(name, "_")
	structName := ""
	for _, name := range names {
		structName = structName + firstToUpper(name)
	}

	return structName
}

func typeConversion(maps []map[string]interface{}, pkName string, t *TableStruct, dbs *DBS) map[string]interface{} {

	info := make(map[string]interface{})

	//4.把maps循环  将date_type 改成对应golang的数据类型
	for _, m := range maps {

		dataType := m["DATA_TYPE"].(string)
		dataType = strings.ToUpper(dataType) //转为大写
		//5.转换类型
		//由于sting类型比较多 为了效率问题 直接放到else里面去了
		if dataType == "DATETIME" || dataType == "TIMESTAMP" || dataType == "DATE" || dataType == "TIME" || dataType == "TIME WITH TIME ZONE" || dataType == "TIMESTAMP WITH TIME ZONE" || dataType == "TIMESTAMP WITH LOCAL TIME ZONE" || dataType == "DATETIME WITH TIME ZONE" {

			dataType = "time.Time"

		} else if dataType == "INT" || dataType == "INTEGER" {

			dataType = "int"

		} else if dataType == "BIGINT" {

			dataType = "int64"

		} else if dataType == "SMALLINT" || dataType == "MEDIUMINT" {
			dataType = "int32"

		} else if dataType == "FLOAT" {

			dataType = "float32"

		} else if dataType == "DOUBLE" || dataType == "REAL" || dataType == "DOUBLE PRECISION" {

			dataType = "float64"

		} else if dataType == "DECIMAL" || dataType == "NUMBER" || dataType == "NUMERIC" || dataType == "DEC" {

			dataType = "decimal.Decimal"

		} else if dataType == "TINYINT" {

			dataType = "int8"

		} else if dataType == "BIT" || dataType == "BYTE" {

			dataType = "byte"
		} else if dataType == "BLOB" {

			dataType = "[]byte"
		} else {

			dataType = "string"
		}

		//5.记录各个字段信息
		m["DATA_TYPE"] = dataType
		fieldName := camelCaseName(m["COLUMN_NAME"].(string))
		m["field"] = fieldName

		//记录主键名称
		//设置主键的struct属性名称
		if m["COLUMN_NAME"].(string) == pkName {
			info["pkField"] = fieldName
			info["ptype"] = dataType
		}

	}

	//6.在这里生成结构体文件需要使用的信息

	info["tableName"] = t.TableName       // 表名
	info["TableComment"] = t.TableComment // 表注释
	info["columns"] = maps                // 结构体字段
	info["pkName"] = pkName               // 主键
	info["case1"] = "string"              //	情况1 如果主键不是 string类型  用于service代码生成
	info["case2"] = ""                    //  情况2 如主键为空     用于service代码生成
	structName := t.TableName             // 实体类名字
	if strings.HasPrefix(structName, "t_") {
		structName = structName[2:]
	}

	structName = camelCaseName(structName) + "Struct" // 驼峰命名
	info["structName"] = structName
	info["pname"] = firstToLower(structName)            //	形参名称
	info["packageName"] = dbs.PackageName               //结构体包名
	info["tableComment"] = t.TableComment               //表注释
	info["servicePackageName"] = dbs.ServicePackageName // 逻辑层包名
	info["StructImportName"] = dbs.StructImportName

	return info
}
